package com.haohan.cloud.scm.supply.core.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.haohan.cloud.scm.api.constant.ScmCacheNameConstant;
import com.haohan.cloud.scm.api.constant.enums.manage.MerchantStatusEnum;
import com.haohan.cloud.scm.api.constant.enums.manage.ShopLevelEnum;
import com.haohan.cloud.scm.api.manage.entity.Merchant;
import com.haohan.cloud.scm.api.manage.entity.UPassport;
import com.haohan.cloud.scm.api.manage.req.MerchantFeignReq;
import com.haohan.cloud.scm.api.manage.vo.MerchantShopVO;
import com.haohan.cloud.scm.api.manage.vo.MerchantVO;
import com.haohan.cloud.scm.api.manage.vo.ShopVO;
import com.haohan.cloud.scm.api.supply.dto.SupplySqlDTO;
import com.haohan.cloud.scm.api.supply.entity.Supplier;
import com.haohan.cloud.scm.api.supply.entity.SupplyOrder;
import com.haohan.cloud.scm.api.supply.req.supplier.SupplierEditReq;
import com.haohan.cloud.scm.api.supply.req.supplier.SupplierQueryReq;
import com.haohan.cloud.scm.api.supply.vo.SupplierMerchantInfoVO;
import com.haohan.cloud.scm.api.supply.vo.SupplierVO;
import com.haohan.cloud.scm.common.tools.exception.ErrorDataException;
import com.haohan.cloud.scm.common.tools.thread.ScmGlobalThreadPool;
import com.haohan.cloud.scm.supply.core.ScmSupplierCoreService;
import com.haohan.cloud.scm.supply.service.SupplierService;
import com.haohan.cloud.scm.supply.service.SupplyOrderService;
import com.haohan.cloud.scm.supply.utils.ScmSupplyUtils;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDept;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import lombok.AllArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author dy
 * @date 2020/4/16
 */
@Service
@AllArgsConstructor
public class ScmSupplierCoreServiceImpl implements ScmSupplierCoreService {

    private final SupplierService supplierService;
    private final ScmSupplyUtils scmSupplyUtils;
    private final SupplyOrderService supplyOrderService;

    @Override
    @Cacheable(value = ScmCacheNameConstant.SUPPLY_SUPPLIER_MERCHANT_INFO, key = "#supplierId")
    public SupplierMerchantInfoVO fetchMerchantInfo(String supplierId) {
        Supplier supplier = supplierService.getById(supplierId);
        if (null == supplier) {
            throw new ErrorDataException("供应商有误");
        }
        MerchantShopVO merchantShopVO = scmSupplyUtils.fetchMerchantShop(supplier.getMerchantId());
        ShopVO shop = merchantShopVO.getShopList().stream()
                .filter(item -> item.getShopLevel() == ShopLevelEnum.pds)
                .findFirst().orElseThrow(() -> new ErrorDataException("供应商无采购配送店铺"));
        SupplierMerchantInfoVO result = new SupplierMerchantInfoVO();
        result.setMerchantId(merchantShopVO.getMerchantId());
        result.setMerchantName(merchantShopVO.getMerchantName());
        result.setShopId(shop.getShopId());
        result.setShopName(shop.getName());
        result.setShopList(merchantShopVO.getShopList());
        return result;
    }

    @Override
    public List<Supplier> findListByMerchant(String merchantId) {
        if (StrUtil.isEmpty(merchantId)) {
            return new ArrayList<>(8);
        }
        return supplierService.list(Wrappers.<Supplier>query().lambda()
                .eq(Supplier::getMerchantId, merchantId)
        );
    }

    /**
     * 获取已有供应商的商家列表
     *
     * @return
     */
    @Override
    public List<MerchantVO> findMerchantListOfSupplier() {
        SupplySqlDTO query = new SupplySqlDTO();
        Set<String> merchantIdSet = supplierService.findSupplyMerchantList(query);
        if (merchantIdSet.isEmpty()) {
            return new ArrayList<>(4);
        }
        MerchantFeignReq req = new MerchantFeignReq();
        req.setMerchantIdSet(merchantIdSet);
        req.setStatus(MerchantStatusEnum.enabled);
        return scmSupplyUtils.findMerchantList(req);
    }

    @Override
    public IPage<SupplierVO> findPage(Page<Supplier> page, SupplierQueryReq req) {
        IPage<Supplier> supplierPage = supplierService.page(page, Wrappers.query(req.transTo())
                .orderByAsc("sort + 0")
                .orderByDesc("create_date")
                .lambda()
                .like(StrUtil.isNotEmpty(req.getMerchantName()), Supplier::getMerchantName, req.getMerchantName())
                .like(StrUtil.isNotEmpty(req.getSupplierName()), Supplier::getSupplierName, req.getSupplierName())
                .like(StrUtil.isNotEmpty(req.getShortName()), Supplier::getShortName, req.getShortName())
                .like(StrUtil.isNotEmpty(req.getContact()), Supplier::getContact, req.getContact())
                .like(StrUtil.isNotEmpty(req.getTelephone()), Supplier::getTelephone, req.getTelephone())
                .like(StrUtil.isNotEmpty(req.getAddress()), Supplier::getAddress, req.getAddress())
                .like(StrUtil.isNotEmpty(req.getTags()), Supplier::getTags, req.getTags())
                .like(StrUtil.isNotEmpty(req.getArea()), Supplier::getArea, req.getArea())
        );
        IPage<SupplierVO> result = new Page<>(supplierPage.getCurrent(), supplierPage.getSize(), supplierPage.getTotal());
        result.setRecords(supplierPage.getRecords().stream()
                .map(SupplierVO::new)
                .collect(Collectors.toList())
        );
        return result;
    }

    /**
     * 供应商信息带 部门、角色
     *
     * @param supplierId
     * @return
     */
    @Override
    public SupplierVO fetchInfoWithRole(String supplierId) {
        Supplier supplier = supplierService.getById(supplierId);
        if (null == supplier) {
            throw new ErrorDataException("供应商有误");
        }
        SupplierVO result = new SupplierVO(supplier);
        // 角色、部门
        UserInfo userInfo = scmSupplyUtils.fetchUserById(supplier.getUserId());
        if (null != userInfo) {
            List<Integer> list = new ArrayList<>(userInfo.getRoles().length);
            list.addAll(Arrays.asList(userInfo.getRoles()));
            result.setRoleList(list);
            String deptId = null;
            if (userInfo.getSysUser() != null && userInfo.getSysUser().getDeptId() != null) {
                deptId = userInfo.getSysUser().getDeptId().toString();
            }
            SysDept dept = scmSupplyUtils.fetchDeptById(deptId);
            if (dept != null) {
                result.setDeptName(dept.getName());
                result.setDeptId(deptId);
            }
        } else {
            result.setRoleList(new ArrayList<>(0));
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addSupplier(SupplierEditReq req) {
        //  验证手机号、名称是否重复
        checkNameAndTelephone(req.getSupplierName(), req.getTelephone());
        Supplier supplier = req.transTo();
        // 商家
        merchantHandle(supplier);
        // 新增平台用户 角色、部门
        SysDept dept = scmSupplyUtils.fetchDeptById(req.getDeptId());
        UserDTO user = fetchUserDTO(supplier, dept, req.getRoleIds());
        user = scmSupplyUtils.addUser(user);
        supplier.setUserId(user.getUserId().toString());
        supplier.setPassportId(user.getOscId());
        supplier.setId(null);
        return supplierService.save(supplier);
    }

    private void merchantHandle(Supplier supplier) {
        Merchant merchant = scmSupplyUtils.fetchMerchantById(supplier.getMerchantId());
        if (null == merchant) {
            throw new ErrorDataException("供应商家有误");
        }
        supplier.setMerchantName(merchant.getMerchantName());
        // 设置平台商家, 供应商使用原系统时需要
        Merchant pm = scmSupplyUtils.fetchPlatformMerchant();
        supplier.setPmId(pm.getId());
    }

    private UserDTO fetchUserDTO(Supplier supplier, SysDept dept, String roleIds) {
        // 角色、user
        List<Integer> roleList = new ArrayList<>(10);
        if (StrUtil.isNotEmpty(roleIds)) {
            String[] roleArray = StrUtil.split(roleIds, StrUtil.COMMA);
            for (String s : roleArray) {
                roleList.add(Integer.valueOf(s));
            }
        }
        UserDTO user = new UserDTO();
        user.setRole(roleList);
        if (null != dept) {
            user.setDeptId(dept.getDeptId());
        }
        if (StrUtil.isNotEmpty(supplier.getUserId())) {
            user.setUserId(Integer.valueOf(supplier.getUserId()));
        }
        user.setUsername(supplier.getSupplierName());
        // 密码默认手机号
        user.setPassword(supplier.getTelephone());
        user.setPhone(supplier.getTelephone());
        // 默认user不可登录后台
        user.setLockFlag(CommonConstants.STATUS_LOCK);
        return user;
    }

    private void checkNameAndTelephone(String supplierName, String telephone) {
        Supplier exist = supplierService.fetchByTelephone(telephone);
        if (null != exist) {
            throw new ErrorDataException("该手机号已存在供应商");
        }
        exist = supplierService.fetchByName(supplierName);
        if (null != exist) {
            throw new ErrorDataException("该名称已存在供应商");
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modifySupplier(SupplierEditReq req) {
        Supplier exist = supplierService.getById(req.getId());
        if (null == exist) {
            throw new ErrorDataException("供应商有误");
        }
        boolean updateNameFlag = !StrUtil.equals(req.getSupplierName(), exist.getSupplierName());
        String name = updateNameFlag ? req.getSupplierName() : "";
        String telephone = StrUtil.equals(req.getTelephone(), exist.getTelephone()) ? "" : req.getTelephone();
        // 验证 修改的  手机号、名称是否重复
        checkNameAndTelephone(name, telephone);
        Supplier supplier = req.transTo();
        // 商家
        merchantHandle(supplier);
        SysDept dept = scmSupplyUtils.fetchDeptById(req.getDeptId());
        UserDTO user = fetchUserDTO(supplier, dept, req.getRoleIds());
        if (StrUtil.isNotEmpty(exist.getUserId())) {
            // 不修改密码
            user.setPassword(null);
            user.setUserId(Integer.valueOf(exist.getUserId()));
            if (!scmSupplyUtils.updateUser(user)) {
                return false;
            }
            // 若无uid需新增 修改手机号、名称时更新
            if (StrUtil.isEmpty(exist.getPassportId()) || StrUtil.isNotEmpty(telephone) || updateNameFlag) {
                UPassport passport = new UPassport();
                passport.setLoginName(supplier.getSupplierName());
                passport.setTelephone(supplier.getTelephone());
                passport.setAvatar("");
                supplier.setPassportId(scmSupplyUtils.addUPassPort(passport).getId());
            }
        } else {
            user = scmSupplyUtils.addUser(user);
            supplier.setUserId(user.getUserId().toString());
            supplier.setPassportId(user.getOscId());
        }
        boolean flag = supplierService.updateById(supplier);
        // 修改名称时 关联表 更新
        if (updateNameFlag) {
            allUpdateSupplierName(exist.getId(), name);
        }
        return flag;
    }

    /**
     * 供应商名称修改 全更新
     *
     * @param supplierId
     * @param supplierName
     */
    private void allUpdateSupplierName(String supplierId, String supplierName) {
        ScmGlobalThreadPool.getExecutor().execute(() -> {
            // 供应订单中
            SupplyOrder supplyOrder = new SupplyOrder();
            supplyOrder.setSupplierName(supplierName);
            supplyOrderService.update(supplyOrder, Wrappers.<SupplyOrder>update().lambda()
                    .eq(SupplyOrder::getSupplierId, supplierId)
            );
        });

    }

    /**
     * 供应商删除
     *
     * @param supplierId
     * @return
     */
    @Override
    public boolean deleteSupplier(String supplierId) {
        Supplier supplier = supplierService.getById(supplierId);
        if (null == supplier) {
            throw new ErrorDataException("供应商有误");
        }
        // 供应商订单数
        int num = supplyOrderService.count(Wrappers.<SupplyOrder>query().lambda()
                .eq(SupplyOrder::getSupplierId, supplierId)
        );
        if (num > 0) {
            throw new ErrorDataException("该供应商有供应订单存在, 不可删除");
        }
        // 删除user
        scmSupplyUtils.deleteUser(supplier.getUserId());
        return supplierService.removeById(supplierId);
    }

    /**
     * 供应商商家名称修改
     *
     * @param merchantId
     * @param merchantName
     * @return
     */
    @Override
    public boolean updateMerchantName(String merchantId, String merchantName) {
        if (StrUtil.isEmpty(merchantId) || StrUtil.isEmpty(merchantName)) {
            throw new ErrorDataException("缺少参数merchantId、merchantName");
        }
        Supplier update = new Supplier();
        update.setMerchantName(merchantName);
        return supplierService.update(update, Wrappers.<Supplier>query().lambda()
                .eq(Supplier::getMerchantId, merchantId)
        );
    }
}
